package com.china08.yxyapi.service.mg.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.math3.stat.descriptive.moment.Skewness;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.china08.yxyapi.api.manage.tec.teaching.scoreport.baseanalysis.BaseAnalysisReportController;
import com.china08.yxyapi.config.RabbitConfig;
import com.china08.yxyapi.entity.mg.scoreport.Exam;
import com.china08.yxyapi.entity.mg.scoreport.ExamStudent;
import com.china08.yxyapi.entity.mg.scoreport.ExamStudent.StuQuesScore;
import com.china08.yxyapi.entity.mg.scoreport.report.ExamBaseAnalyse;
import com.china08.yxyapi.entity.mg.scoreport.report.ExamBaseAnalyse.ScoreLevel;
import com.china08.yxyapi.repository.mg.scoreport.ExamBaseAnalyseRepository;
import com.china08.yxyapi.repository.mg.scoreport.ExamRepository;
import com.china08.yxyapi.repository.mg.scoreport.ExamStudentRepository;
import com.china08.yxyapi.service.mg.ExamBaseAnalyseService;
import com.china08.yxyapi.util.SpringContextUtil;
import com.china08.yxyapi.util.algorithm.ReportAlgorithm;
import com.china08.yxyapi.util.algorithm.ScoreAlgorithm;
import com.mathworks.toolbox.javabuilder.MWException;

@Service
public class ExamBaseAnalyseServiceImpl implements ExamBaseAnalyseService {

    @Autowired
    private ExamRepository examRepository;

    @Autowired
    private ExamBaseAnalyseRepository examBaseAnalyseRepository;

    @Autowired
    private ExamStudentRepository examStudentRepository;

    @Override
    public List<Object> getReportMessage(String examBaseId, String examId, Map<Integer, Integer> fineRank) {
        ExamBaseAnalyse examBaseAnalyse = new ExamBaseAnalyse();
        if (examBaseId != null && !examBaseId.equals("")) {
            examBaseAnalyse = examBaseAnalyseRepository.findById(examBaseId);
        }
        // ------评语------//
        Exam exam = examRepository.findById(examId);
        // exam.setId(examId);
        Integer studentCountJoin = exam.getStudents().size();
        Long studentCountNotJoin = examStudentRepository.countByExamAndStuTotalScoreNot(exam, -1);
        // 卷面总成绩
        Integer totalScore = examBaseAnalyse.getExam().getTotalScore();

        Integer youxiu1 = 0;
        Integer bujige1 = 0;
        Integer bujigeguocha = 0;
        Integer jige = 0;
        Integer lianghao = 0;
        for (Integer key : fineRank.keySet()) { // key: 5,4,3,2,1 分别对应
                                                // "优秀","良好","及格","不及格","不及格过差"</br>
            if (key == 5) {
                youxiu1 = fineRank.get(key);
            }
            if (key == 2) {
                bujige1 = fineRank.get(key);
            }
            if (key == 1) {
                bujigeguocha = fineRank.get(key);
            }
            if (key == 3) {
                jige = fineRank.get(key);
            }
            if (key == 4) {
                lianghao = fineRank.get(key);
            }
        }
        // 优秀的人占的百分比
        Long youxiuCount = examStudentRepository.countByExamAndStuTotalScoreGreaterThanEqual(exam, youxiu1);
        DecimalFormat df = new DecimalFormat("######0.00");
        double bb = (double) youxiuCount / studentCountNotJoin * 100;
        double aa = Math.round(bb * 100) * 0.01d;
        double cc = (Double.valueOf(df.format(aa)));
        // 良好的人占百分比
        Long liang = examStudentRepository.countByExamAndStuTotalScoreBetween(exam, lianghao - 0.1, youxiu1);
        bb = (double) liang / studentCountNotJoin * 100;
        aa = Math.round(bb * 100) * 0.01d;
        double dd = (Double.valueOf(df.format(aa)));
        // 及格的人占百分比
        Long ji = examStudentRepository.countByExamAndStuTotalScoreBetween(exam, jige - 0.1, lianghao);
        bb = (double) ji / studentCountNotJoin * 100;
        aa = Math.round(bb * 100) * 0.01d;
        double ee = (Double.valueOf(df.format(aa)));
        // 不及格的人占百分比
        Long buji = examStudentRepository.countByExamAndStuTotalScoreLessThan(exam, bujige1);
        bb = (double) buji / studentCountNotJoin * 100;
        aa = Math.round(bb * 100) * 0.01d;
        double ff = (Double.valueOf(df.format(aa)));
        // 不及格-过差的人占百分比
        Long guochacha = examStudentRepository.countByExamAndStuTotalScoreLessThan(exam, bujigeguocha);
        bb = 100 - cc - dd - ee - ff;
        double gg = 0.0;
        if (bb < 0) {
            ff = (Double.valueOf(df.format(bb + ff)));
            bb = 0;
        }

        // 不及格的人占的百分比
        // Long bujigeCount =
        // examStudentRepository.countByExamAndStuTotalScoreBetween(exam,
        // bujigeguocha,
        // bujige1 + 1);
        // Integer bujige = (int) (Double.valueOf(df.format((double) bujigeCount
        // / studentCountNotJoin)) * 100);
        // // 不及格的人占的百分比
        // Long bujigeCount2 =
        // examStudentRepository.countByExamAndStuTotalScoreLessThan(exam,jige);
        // Integer bujige3 = (int) (Double.valueOf(df.format((double)
        // bujigeCount2 / studentCountNotJoin)) * 100);
        //// Integer bujige = (int) (Double.parseDouble(df.format((double)
        // bujigeCount / studentCountNotJoin)) * 100);
        // // 过差的人占的百分比
        // Long guochaCount =
        // examStudentRepository.countByExamAndStuTotalScoreLessThan(exam,
        // bujigeguocha);
        // Integer guocha = (int) (Double.valueOf(df.format((double) guochaCount
        // / studentCountNotJoin)) * 100);
        // // 良好和及格的百分比
        //// Long lianghaoJigeCount =
        // examStudentRepository.countByExamAndStuTotalScoreBetween(exam, jige,
        // youxiu1+1);
        // Integer lianghaoJige = (100-youxiu-bujige3);
        String remark = "";
        if ((studentCountJoin - studentCountNotJoin) == 0) { // 如果缺考人数为0
            remark += "有效录入成绩人数" + studentCountNotJoin + "人，无缺考学生。";
        } else {
            remark += "有效录入成绩人数" + studentCountNotJoin + "人，缺考人数" + (studentCountJoin - studentCountNotJoin)
                    + "人，如有学校有要求，请接下来的时间内安排考试。";
        }

        // Integer bujige4 = bujige3;

        remark += "在本次测验中，卷面总成绩为" + totalScore + "分。";
        if (cc != 0) {
            remark += "其中优秀占到全班人数的" + cc + "%,";
        } else {
            remark += "其中班级内没有达到优秀的学生,";
        }
        if ((ff + gg) != 0) {
            bb = ff + gg;
            aa = Math.round(bb * 100) * 0.01d;
            remark += "不及格占到全班" + aa + "%，";
            if (gg != 0) {
                remark += "其中过差的学生达到" + gg + "%，";
            }
        }
        if ((dd + ee) != 0) {
            bb = dd + ee;
            aa = Math.round(bb * 100) * 0.01d;
            remark += "良好和及格人数占到全班人数" + aa + "%。";
        }

        double a = cc;
        double b = dd + ee;
        double c = (ff + gg);
        double maxNum = a >= b ? a >= c ? a : c : b >= c ? b : c;
        if (maxNum == a || maxNum == a && maxNum == b && maxNum == c || maxNum == a && maxNum == b
                || maxNum == a && maxNum == c) {// 优秀人多
            remark += "本次考试学生主要集中在优秀，学生已经适应了当前试卷难度，请在下次对试卷难度进行调整。";
        } else if (maxNum == b || maxNum == b && maxNum == c) {// 中等人多
            remark += "本次考试学生主要集中在中分段中，需要针对这部分学生的实际情况进行拔高和巩固基础。";
        } else if (maxNum == c) {// 低等人多
            remark += "本次考试学生主要集中在不及格中，不及格低分段人数达到" + buji + "人，需要针对这部分学生进行学习基础的提高。";
        }
        // 本次考试第一名
        ExamStudent examStudentTop = examStudentRepository.findTopByExamOrderByStuTotalScoreDescCreatedDateAsc(exam);
        /*
         * List<ExamStudent> examStudentLst =
         * examStudentRepository.findByExamAndStuTotalScore(exam,examStudentTop.
         * getStuTotalScore()); if (examStudentLst != null &&
         * examStudentLst.size()>0) { String studentNickLst = ""; for
         * (ExamStudent examStudent : examStudentLst) { studentNickLst +=
         * examStudent.getStudentNick()+","; } remark +=
         * "本次考试第一名为"+studentNickLst.substring(0,
         * studentNickLst.length()-1)+"同学，老师可以针对排名前五的同学进行适当的表扬。"; }
         */
        remark += "本次考试第一名为" + examStudentTop.getStudentNick() + "同学，老师可以针对排名前五的同学进行适当的表扬。";
        // 本次考试最后一名
        List<ExamStudent> examStudentBottom = examStudentRepository
                .findByExamOrderByStuTotalScoreDescCreatedDateAsc(exam);
        /*
         * List<ExamStudent> examStudentLst2 =
         * examStudentRepository.findByExamAndStuTotalScore(exam,
         * examStudentBottom.getStuTotalScore());
         */
        if (examStudentBottom != null && examStudentBottom.size() > 0) {
            String studentNickLstBottom = "";
            if (examStudentBottom.size() >= 3) {
                examStudentBottom = examStudentBottom.subList(examStudentBottom.size() - 3, examStudentBottom.size());
            }
            for (ExamStudent examStudent : examStudentBottom) {
                studentNickLstBottom += examStudent.getStudentNick() + ",";
            }
            remark += studentNickLstBottom.substring(0, studentNickLstBottom.length() - 1)
                    + "同学，在本次考试中考试成绩垫底，考试成绩是平时学习的检测，老师可以和家长进行沟通，一起帮助学生成长。";
        }
        // remark += examStudentBottom.getStudentNick() +
        // "同学，在本次考试中考试成绩垫底，考试成绩是平时学习的检测，老师可以和家长进行沟通，一起帮助学生成长。";
        // ------------------
        examBaseAnalyse.setRemark(remark);
        examBaseAnalyse.setFineRank(fineRank);
        examBaseAnalyseRepository.save(examBaseAnalyse);
        ExamBaseAnalyse examBaseAnalysee = examBaseAnalyseRepository.findById(examBaseId);
        BaseAnalysisReportController.ExamStudentModel examStudentModel = null;
        List<ExamStudent> examStudent = examStudentRepository.findByExamOrderByStuTotalScoreDescCreatedDateAsc(exam);
        List<BaseAnalysisReportController.ExamStudentModel> examStudentModelLst = new ArrayList<BaseAnalysisReportController.ExamStudentModel>();
        for (ExamStudent examStudent2 : examStudent) {
            examStudentModel = new BaseAnalysisReportController().new ExamStudentModel();
            examStudentModel.studentNick = examStudent2.getStudentNick();
            examStudentModel.stuTotalScore = examStudent2.getStuTotalScore();
            examStudentModelLst.add(examStudentModel);
        }
        List<Object> objs = new ArrayList<Object>();
        objs.add(examStudentModelLst);
        objs.add(examBaseAnalysee.getDifficultDegree());
        objs.add(examBaseAnalysee.getRemark());
        return objs;
    }

    // 创建基础分析
    @Override
    public void saveExamBaseAnalyse(String examId) throws MWException {
        BigDecimal bd = null;

        Exam exam = examRepository.findOne(examId);
        exam.setStatus(1);
        examRepository.save(exam);
        List<ExamStudent> examStu = examStudentRepository.findByExam(exam);

        ExamBaseAnalyse examBaseAnalyse = null;
        examBaseAnalyse = examBaseAnalyseRepository.findByExam(exam);
        if (examBaseAnalyse == null) {
            examBaseAnalyse = new ExamBaseAnalyse();
        }
        examBaseAnalyse.setExam(exam);

        // 成绩集合
        List<Double> scoreLst = new ArrayList<>();
        for (ExamStudent examStudent : examStu) {
            scoreLst.add(examStudent.getStuTotalScore());
        }

        // 人数范围所需成绩集合（移除记录使用）
        List<Double> hsLst = new ArrayList<>();
        hsLst.addAll(scoreLst);
        // 考试满分分数
        int examTotalScore = exam.getTotalScore();
        // 迭代基数数字
        int baseNum = 0;

        // 优良分布图
        Map<Integer, Integer> fineRankMap = new HashMap<Integer, Integer>();

        switch (examTotalScore) {
        case 100:
            baseNum = 10;
            break;
        case 120:
            baseNum = 12;
            break;
        case 150:
            baseNum = 15;
            break;
        case 180:
            baseNum = 18;
            break;
        }

        fineRankMap.put(5, (int) (examTotalScore * 0.9));
        fineRankMap.put(4, (int) (examTotalScore * 0.8));
        fineRankMap.put(3, (int) (examTotalScore * 0.6));
        fineRankMap.put(2, (int) (examTotalScore * 0.6));
        fineRankMap.put(1, (int) (examTotalScore * 0.45));
        examBaseAnalyse.setFineRank(fineRankMap);

        Map<String, Integer> histogramMap = new HashMap<String, Integer>();
        // 循环取出范围
        for (int i = 0; i <= examTotalScore - baseNum; i += baseNum) {
            int count = 0;
            for (int j = 0; j < hsLst.size(); j++) {
                if (i == examTotalScore - baseNum) {
                    if (i <= hsLst.get(j) && hsLst.get(j) <= (i + baseNum)) {
                        count++;
                        hsLst.remove(j);
                        j = -1;
                    }
                } else {
                    if (i <= hsLst.get(j) && hsLst.get(j) < (i + baseNum)) {
                        count++;
                        hsLst.remove(j);
                        j = -1;
                    }
                }
            }
            histogramMap.put((i + baseNum) + "", count);
        }

        // 成绩范围
        examBaseAnalyse.setHistogram(histogramMap);
        // 平均分
        double avgScore = ScoreAlgorithm.scoreAvg(scoreLst);
        examBaseAnalyse.setAverage(avgScore);
        // 最高分
        scoreLst.sort((h1, h2) -> h2.compareTo(h1));
        examBaseAnalyse.setMax(scoreLst.get(0));
        // 最低分
        scoreLst.sort((h1, h2) -> h1.compareTo(h2));
        examBaseAnalyse.setMin(scoreLst.get(0));
        // 得分率
        double obtainScoreAvg = ReportAlgorithm.correct(scoreLst, examTotalScore) * 100;
        bd = new BigDecimal(obtainScoreAvg);
        examBaseAnalyse.setScoreRate(bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        // 失分率
        double lostScoreAvg = 100 - obtainScoreAvg;
        bd = new BigDecimal(lostScoreAvg);
        examBaseAnalyse.setLostScoreRate(bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        // 成绩等级？
        Map<String, ScoreLevel> scoreLevelMap = new HashMap<String, ScoreLevel>();
        // 循环取出范围
        hsLst.clear();
        hsLst.addAll(scoreLst);
        int spaceNum = 0;
        List<String> mapKey = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            double count = 0d;
            String flag = "";
            ScoreLevel sL = examBaseAnalyse.new ScoreLevel();
            for (int j = 0; j < hsLst.size(); j++) {
                if (i == 0) {// 高分段
                    flag = "high";
                    if (examTotalScore * 0.9 <= hsLst.get(j) && hsLst.get(j) <= examTotalScore) {
                        count++;
                        hsLst.remove(j);
                        j = -1;
                    }
                } else if (i == 1) {// 中分段
                    flag = "middle";
                    if (examTotalScore * 0.6 <= hsLst.get(j) && hsLst.get(j) < examTotalScore * 0.9) {
                        count++;
                        hsLst.remove(j);
                        j = -1;
                    }
                } else {// 低分段
                    flag = "low";
                    if (0 <= hsLst.get(j) && hsLst.get(j) < examTotalScore * 0.6) {
                        count++;
                        hsLst.remove(j);
                        j = -1;
                    }
                }
            }
            // 集中度
            if (spaceNum < count) {
                if (mapKey.size() > 0) {
                    for (String key : mapKey) {
                        scoreLevelMap.get(key).concentrate = "集中度：低";
                    }
                }
                spaceNum = (int) count;
                mapKey.add(flag);
                sL.concentrate = "集中度：高";

            } else if (spaceNum == count) {
                spaceNum = (int) count;
                mapKey.add(flag);
                sL.concentrate = "集中度：高";
            } else {
                sL.concentrate = "集中度：低";
            }
            // 人数
            sL.count = (int) count;
            // 百分比
            bd = new BigDecimal(count / scoreLst.size() * 100);
            sL.rate = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            switch (i) {
            case 0:
                sL.level = (int) (examTotalScore * 0.9) + "~" + examTotalScore;
                scoreLevelMap.put("high", sL);
                break;
            case 1:
                sL.level = (int) (examTotalScore * 0.6) + "~" + (int) (examTotalScore * 0.9 - 1);
                scoreLevelMap.put("middle", sL);
                break;
            case 2:
                sL.level = 0 + "~" + (int) (examTotalScore * 0.6 - 1);
                scoreLevelMap.put("low", sL);
                break;
            }
        }
        examBaseAnalyse.setScoreLevel(scoreLevelMap);

        // 试卷难度
        if (exam.getQuestions() != null) {
            if (exam.getQuestions().size() > 0) {
                // 拥有小题时
                int quesNum = examStu.get(0).getStuQuesScores().size();
                List<Double> itemDifficultyLst = new ArrayList<Double>();
                List<Double> fullMarksLst = new ArrayList<Double>();
                for (int i = 1; i <= quesNum; i++) {
                    List<Double> quesLst = new ArrayList<Double>();
                    int fullScore = 0;
                    for (ExamStudent examStudent : examStu) {
                        for (StuQuesScore stuQues : examStudent.getStuQuesScores()) {
                            if (stuQues.order_num == i) {
                                quesLst.add(stuQues.stu_score);
                                fullScore = stuQues.score;
                                break;
                            }
                        }
                    }
                    fullMarksLst.add((double) fullScore);
                    itemDifficultyLst.add(ScoreAlgorithm.itemDifficulty(quesLst, fullScore));
                }
                // 难度系数
                double d = ScoreAlgorithm.testDifficulty(itemDifficultyLst, fullMarksLst);
                if (d >= 0.7) {
                    examBaseAnalyse.setDifficultDegree(1);
                } else if (d >= 0.4 && d < 0.7) {
                    examBaseAnalyse.setDifficultDegree(2);
                } else if (d >= 0.1 && d < 0.4) {
                    examBaseAnalyse.setDifficultDegree(3);
                } else if (d < 0.1) {
                    examBaseAnalyse.setDifficultDegree(4);
                }
                // 拥有小题时触发小题分析
                SpringContextUtil.getBean(RabbitTemplate.class).convertAndSend(RabbitConfig.ClASS_EXAMQUES_REPORT,
                        examId);
            } else {
                Skewness skewness = new Skewness();
                int size = scoreLst.size();
                double[] arr = new double[size];
                for (int i = 0; i < scoreLst.size(); i++) {
                    arr[i] = scoreLst.get(i);
                }
                double getSk = skewness.evaluate(arr);
                if (getSk > 0) {
                    if (avgScore >= examTotalScore * 0.9) {// 优秀：易
                        examBaseAnalyse.setDifficultDegree(1);
                    } else if (avgScore >= examTotalScore * 0.6 && avgScore < examTotalScore * 0.9) {// 良好、及格：一般
                        examBaseAnalyse.setDifficultDegree(2);
                    } else if (avgScore >= examTotalScore * 0.45 && avgScore < examTotalScore * 0.6) {// 不及格：难
                        examBaseAnalyse.setDifficultDegree(3);
                    } else if (avgScore < examTotalScore * 0.45) {// 过差：非常难
                        examBaseAnalyse.setDifficultDegree(4);
                    }
                } else if (getSk == 0) {
                    if (avgScore >= examTotalScore * 0.6) {// 优秀、良好、及格：一般
                        examBaseAnalyse.setDifficultDegree(2);
                    } else if (avgScore < examTotalScore * 0.6) {// 不及格、过差：难
                        examBaseAnalyse.setDifficultDegree(3);
                    }
                } else if (getSk < 0) {
                    if (avgScore >= examTotalScore * 0.8) {// 优秀、良好：一般
                        examBaseAnalyse.setDifficultDegree(2);
                    } else if (avgScore >= examTotalScore * 0.6 && avgScore < examTotalScore * 0.8) {// 及格：难
                        examBaseAnalyse.setDifficultDegree(3);
                    } else if (avgScore < examTotalScore * 0.6) {// 不及格、过差：非常难
                        examBaseAnalyse.setDifficultDegree(4);
                    }
                }
            }
        } else {
            Skewness skewness = new Skewness();
            int size = scoreLst.size();
            double[] arr = new double[size];
            for (int i = 0; i < scoreLst.size(); i++) {
                arr[i] = scoreLst.get(i);
            }
            double getSk = skewness.evaluate(arr);
            if (getSk > 0) {
                if (avgScore >= examTotalScore * 0.9) {// 优秀：易
                    examBaseAnalyse.setDifficultDegree(1);
                } else if (avgScore >= examTotalScore * 0.6 && avgScore < examTotalScore * 0.9) {// 良好、及格：一般
                    examBaseAnalyse.setDifficultDegree(2);
                } else if (avgScore >= examTotalScore * 0.45 && avgScore < examTotalScore * 0.6) {// 不及格：难
                    examBaseAnalyse.setDifficultDegree(3);
                } else if (avgScore < examTotalScore * 0.45) {// 过差：非常难
                    examBaseAnalyse.setDifficultDegree(4);
                }
            } else if (getSk == 0) {
                if (avgScore >= examTotalScore * 0.6) {// 优秀、良好、及格：一般
                    examBaseAnalyse.setDifficultDegree(2);
                } else if (avgScore < examTotalScore * 0.6) {// 不及格、过差：难
                    examBaseAnalyse.setDifficultDegree(3);
                }
            } else if (getSk < 0) {
                if (avgScore >= examTotalScore * 0.8) {// 优秀、良好：一般
                    examBaseAnalyse.setDifficultDegree(2);
                } else if (avgScore >= examTotalScore * 0.6 && avgScore < examTotalScore * 0.8) {// 及格：难
                    examBaseAnalyse.setDifficultDegree(3);
                } else if (avgScore < examTotalScore * 0.6) {// 不及格、过差：非常难
                    examBaseAnalyse.setDifficultDegree(4);
                }
            }
        }
        examBaseAnalyseRepository.save(examBaseAnalyse);
    }
}
